package com.qf.Service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.qf.Service.PayService;
import com.qf.config.MQInit;
import com.qf.config.WeChatPayConfig;
import com.qf.entity.Message;
import com.qf.mapper.MessageMapper;
import com.qf.mapper.OrderMapper;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 作者：大狗
 * 时间：2021/7/12 19:59
 */
@Service
public class PayServiceImpl implements PayService {
    private OrderMapper orderMapper;
    private MessageMapper messageMapper;
    private RabbitTemplate availableTemplate;

    public PayServiceImpl(RabbitTemplate availableTemplate,OrderMapper orderMapper,MessageMapper messageMapper) {
        this.orderMapper = orderMapper;
        this.messageMapper = messageMapper;
        this.availableTemplate = availableTemplate;
    }

    public String getUUID(){
       return UUID.randomUUID().toString().replaceAll("-","");
    }

    @Override
    public String getPayUrl(Double price, Integer courseId) {
        try {
            //创建WXPay对象，用于微信支付客户端交互
            WXPay wxPay = new WXPay(new WeChatPayConfig());
            //设置当前订单信息
            HashMap<String ,String> data = new HashMap<>();
            data.put("body","iPhone 12");//设置商品信息
            data.put("fee_type","CNY");//设置支付货币
            data.put("total_fee","1");//设置支付金额
            data.put("out_trade_no",getUUID());//设置当前支付交易号
            data.put("trade_type","NATIVE");//设置交易类型
            data.put("notify_url","http://qxl.free.idcfengye.com/pay/receive");//设置支付完成的回调地址
            //发送请求，获取响应
            Map<String, String> map = wxPay.unifiedOrder(data);
            //System.out.println(map);
            return map.get("code_url");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "支付失败!";
    }

    @Transactional
    @Override
    public Object returnWechat(HttpServletRequest request) {
        Map<String, String> map = null;
        Message message = new Message();
        String messageId = getUUID();
        try {
            //1.微信支付平台会返回xml格式的支付完成响应，需要需要输入流读取
            //获取输入流对象
            ServletInputStream is = request.getInputStream();
            byte[] bs = new byte[1024];
            int len = -1;
            StringBuffer sb = new StringBuffer();
            while ((len=is.read())!=-1){
                //读取内容拼接
                sb.append(new String(bs, 0, len));
            }
            String s = sb.toString();
            //将接收到的xml格式转换成map集合
            map = WXPayUtil.xmlToMap(s);
            message.setId(messageId);
            message.setExchange(MQInit.PAY_EXCHANGE);
            message.setRoutingKey(MQInit.PAY_KEY);
            message.setContent(JSONObject.toJSONString(map));
            message.setStatus(0);
            message.setTryCount(0);
            message.setCreateTime(new Date());
            //表示支付成功
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(map != null && "success".equalsIgnoreCase(map.get("result_code"))){
            //2.响应微信支付平台
            HashMap<String,String> resp = new HashMap<>();
            resp.put("return_code","success");
            resp.put("return_msg","OK");
            resp.put("appid",map.get("appid"));
            resp.put("result_code","success");
            //1.修改订单支付状态（RabbitMQ中间件实现）
            //根据订单号修改支付状态
            orderMapper.updateStatus(map.get("out_trade_no"));
            messageMapper.insert(message);

            /**
             *  CorrelationData 的主要目的是作为 convertAndSend() 方法的第四个参数.
             *  在消息回调的时候 {@link MQInit#rabbitTemplate()} 回调时候, 获取消息的id.
             */
            CorrelationData cd = new CorrelationData(messageId);
            MessageProperties mp = new MessageProperties();
            mp.setCorrelationId(messageId);
            mp.setDeliveryMode(MessageDeliveryMode.PERSISTENT);  // 表示消息为持久化消息
            org.springframework.amqp.core.Message msg = new org.springframework.amqp.core.Message(message.getContent().getBytes(), mp);

            // 往RabbitMQ中发送消息
            availableTemplate.convertAndSend(MQInit.PAY_EXCHANGE,MQInit.PAY_KEY,msg,cd);

            try {
                return WXPayUtil.mapToXml(resp);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "success";
    }
}
